#ifndef List_H
#define List_H
#include "Node.h"
#include<iostream>

using namespace std;

template < typename Dato >
class List
{
    private:
    Node<Dato>* primero;
    unsigned tam;

    public:
        // Constructor
        // PRE:  ninguna
        // POST: construye una lista vacia
        //       - primero apunta a nulo
        //       - tam = 0
        List();

        // Destructor
        // PRE:  lista creada
        // POST: Libera todos los recursos de la lista
        ~List();

        // La lista es vacía?
        // PRE:  lista creada
        // POST: devuelve verdadero si la lista es vacia
        //       falso de lo contrario
        bool lista_vacia();

        // Agregar un elemento a la lista
        // PRE:  lista creada
        // POST: agrega un dato (dentro de un Node) al final
        //       incrementa tam en 1
        void insert(Dato d);

        // Obtener el dato que está en la posición pos
        // PRE:  - lista creada y no vacia
        //       - 0 < pos <= tam
        // POST: devuelve el dato que esta en la posicion pos
        //       se toma 1 como el primero
        Dato get_dato(unsigned pos);

        // PRE:  Lista creada y posicion valida
        // POST: Obtiene el puntero al Node en de la pos
        Node<Dato>* get_Node(unsigned pos);

        // Borrado del Node que está en la posición pos
        // PRE:  - lista creada y no vacia
        //       - 0 < pos <= tam
        // POST: libera el Node que esta en la posición pos
        //       se toma 1 como el primero
        void del_dato(unsigned pos);

        // Obtener el tamaño de la lista
        // PRE:  Lista creada
        // POST: Devuelve tam (cantidad de Nodes de la lista)
        unsigned get_tam();

        // Setea el tamaño de la lista
        // PRE:  Lista creada
        // POST: Setea tam (cantidad de Nodes de la lista)
        void set_tam(unsigned tam);

        // PRE:  Lista creada
        // POST: Obtiene el puntero al primer Node
        Node<Dato>* get_primero();

        // PRE:  Lista creada
        // POST: Obtiene el puntero al último Node
        Node<Dato>* get_ultimo();
};

template < typename Dato >
List<Dato>::List()
{
  primero = 0;
  tam=0;  //ctor
}

template < typename Dato >
List<Dato>::~List()
{
  while (!(this->lista_vacia()))
     this->del_dato(1); //dtor
}

template < typename Dato >
bool List<Dato>::lista_vacia()
{
 return (primero==0);
}

template < typename Dato >
 void List<Dato>::insert(Dato d)
  {
   Node<Dato>* pNode=new Node<Dato>(d);
   Node<Dato>* paux=primero;
    if (this->lista_vacia())
     primero=pNode;
    else
    {
      while (paux->get_siguiente())
      {
        paux=paux->get_siguiente();
      }

    paux->set_siguiente(pNode);
    }
   tam++;

  }

template < typename Dato >
Node<Dato>* List<Dato>::get_Node(unsigned pos)
 {
   Node<Dato>* paux=primero;
   unsigned i=1;
    while (i<pos && paux->get_siguiente())
    {
     paux= paux->get_siguiente();
     i++;
    }

    return paux;

 }

template < typename Dato >
Dato List<Dato>::get_dato(unsigned pos)
{
	   Node<Dato>* paux = this->get_Node(pos);
	   return paux->get_dato();
}

template < typename Dato >
 void List<Dato>::del_dato(unsigned pos)
 {
  Node<Dato>* paux=primero;
   if (pos==1 || !(paux->get_siguiente()))
    {
     primero= paux->get_siguiente();
    }
    else
    {
     unsigned i=1;
     Node<Dato>* pant;
      while (i<pos && paux->get_siguiente())
       {
        pant=paux;
       paux=paux->get_siguiente();
       i++;
       }
     pant->set_siguiente(paux->get_siguiente());
    }
   delete paux;
   tam--;
     }

template < typename Dato >
unsigned List<Dato>::get_tam()
 {
   return tam;
 }

template < typename Dato >
Node<Dato>* List<Dato>::get_primero()
 {
    return this->primero;
 }

template < typename Dato >
Node<Dato>* List<Dato>::get_ultimo()
 {
     Node<Dato>* actual=this->primero;
     Node<Dato>* anterior;
     while (actual) {
        anterior = actual;
        actual = actual->get_siguiente();
     }
     return anterior;
 }
#endif // List_H
